﻿package com.gobang.netmode.clientdata;

import java.io.*;
import java.net.*;
import java.util.Timer;
import java.util.TimerTask;
import java.util.Vector;
import java.util.concurrent.LinkedBlockingQueue;

import javax.swing.text.StyledDocument;

import com.gobang.gobangui.PlayFrame;
import com.gobang.gobangui.MainWindowUI;
import com.gobang.netmode.search.SearchJFrameOfLAN;
import com.gobang.netmode.search.SearchJFrameOfWAN;
import com.gobang.netmode.sendandreceive.Message;
import com.gobang.netmode.sendandreceive.MessageMSG;
import com.gobang.netmode.sendandreceive.Order;
import com.gobang.netmode.sendandreceive.SendAndReceive;
import com.gobang.netmode.util.ClientDataClass;
import com.gobang.netmode.util.Netmode;
import com.gobang.util.chessdata.ChessPoint;



public class ChessClient {
	// 客户信息，并有函数可返回和设置客户的信息
	private static ClientDataClass clientDataClass;
	int chessNum; // 目前的棋子数
	public static Vector<ClientDataClass> clientdataVec; // 房间中所有用户的信息
	private static boolean isWork = false;
	private static boolean isBegin = false;
	private static String IDOfChess;
	private static SendAndReceive sendAndReceive;// 与服务器保持通信
	InetAddress serverAddress;
	static int portOfClientConnectServer;// 服务器的端口
	private static ClientReceiveThread clientReceive;
	private static LinkedBlockingQueue<Message> failMessageQue = new LinkedBlockingQueue<Message>();
	// 用于存储无法发送的消息

	public ChessClient(String Name, String ID, InetAddress serverIP, int port) {// 构造方法
		// TODO Auto-generated constructor stub

		serverAddress = serverIP;
		portOfClientConnectServer = port;
		isWork = true;
		clientdataVec = new Vector<ClientDataClass>();
		try {
			// System.err.println(serverIP);
			Socket socket = new Socket(serverIP, port);
			serverIP = socket.getInetAddress();
			clientDataClass = new ClientDataClass(Name, socket.getLocalAddress(), 0, ID);
			sendAndReceive = new SendAndReceive(socket);
			clientReceive = new ClientReceiveThread(sendAndReceive);
			clientReceive.start();
			joinRoom();// 加入房间
		} catch (IOException e) {

			// TODO Auto-generated catch block
			isWork = false;
			e.printStackTrace();
		}
	}

	public ChessClient(String Name, String ID, String serverIP, int port) {// 构造方法
		// TODO Auto-generated constructor stub

		portOfClientConnectServer = port;
		isWork = true;
		clientdataVec = new Vector<ClientDataClass>();
		try {
			Socket socket = new Socket(serverIP, port);
			serverAddress = socket.getInetAddress();
			clientDataClass = new ClientDataClass(Name, socket.getLocalAddress(), 0, ID);
			sendAndReceive = new SendAndReceive(socket);
			clientReceive = new ClientReceiveThread(sendAndReceive);
			clientReceive.start();
			joinRoom();// 加入房间
		} catch (IOException e) {
			// TODO Auto-generated catch block
			isWork = false;
			e.printStackTrace();
		}
	}

	public ChessClient(String Name, String ID, Socket server) {// 构造方法,这种构造方法最好不用
		// TODO Auto-generated constructor stub
		serverAddress = server.getInetAddress();
		portOfClientConnectServer = server.getPort();
		isWork = true;
		clientdataVec = new Vector<ClientDataClass>(20);
		clientDataClass = new ClientDataClass(Name, server.getLocalAddress(), 0, ID);
		sendAndReceive = new SendAndReceive(server);
		clientReceive = new ClientReceiveThread(sendAndReceive);
		clientReceive.start();
		joinRoom();// 加入房间
	}

	public ChessClient(String Name, String ID, SendAndReceive s) {// 构造方法,针对广域网的构造方法
		// TODO Auto-generated constructor stub
		serverAddress = s.getSocket().getInetAddress();
		portOfClientConnectServer = s.getSocket().getPort();
		isWork = true;
		clientdataVec = new Vector<ClientDataClass>(20);
		sendAndReceive = s;
		clientDataClass = new ClientDataClass(Name, s.getSocket().getLocalAddress(), 0, ID);
		clientReceive = new ClientReceiveThread(s);
		clientReceive.start();
		joinRoom();
	}

	public static Socket reConnectServer() {// 默认是连上本地的服务器
		int connectCount = 5;
		while (connectCount-- > 0) {
			try {
				Socket socket = new Socket(SearchJFrameOfLAN.realLocalIP, portOfClientConnectServer);
				return socket;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
		return null;
	}

	public static Socket reConnectServer(InetAddress serverIP) {//
		// 默认是连上本地的服务器
		int connectCount = 5;
		while (connectCount-- > 0) {
			try {
				Socket socket = new Socket(serverIP, portOfClientConnectServer);
				sendAndReceive.setSocket(socket);
				isWork = true;
				return socket;
			} catch (IOException e) {
				// TODO Auto-generated catch block
				try {
					Thread.sleep(1000);
				} catch (InterruptedException e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				e.printStackTrace();
			}
		}
		return null;
	}

	public static ClientReceiveThread getClientReceiveThread() {
		return clientReceive;
	}

	/***************************
	 * 调用和设置ChessClient变量的函数
	 * 
	 * @param Name
	 **************************************/
	public int getPort() {
		return portOfClientConnectServer;
	}

	public static ClientReceiveThread getClientReceive() {
		return clientReceive;
	}

	public void setPort(int port) {
		portOfClientConnectServer = port;
	}

	public static ClientDataClass getClientDataClass() {
		return clientDataClass;
	}

	public static void setClientDataClass(ClientDataClass clientDataClass) {
		ChessClient.clientDataClass = clientDataClass;
	}

	public static SendAndReceive getSendAndReceive() {
		return sendAndReceive;
	}

	public static void setBegin(boolean isBegin) {
		ChessClient.isBegin = isBegin;
	}

	public static void setClientName(String Name) {
		clientDataClass.setClientName(Name);
	}

	public static void setClientAddress(InetAddress address) {
		clientDataClass.setClientAddress(address);
	}

	public static void setAttribute(int a) {
		clientDataClass.setAttribute(a);
	}

	public static String getClientName() {
		return clientDataClass.getClientName();
	}

	public static InetAddress getClientAddress() {
		return clientDataClass.getClientAddress();
	}

	public static int getAttribute() {
		return clientDataClass.getAttribute();
	}

	public static boolean getIsWork() {
		return isWork;
	}

	public static void setIsWork(boolean b) {
		isWork = b;
	}

	public static boolean getIsBegin() {
		return isBegin;
	}

	public static LinkedBlockingQueue<Message> getFailMessageQue() {
		return failMessageQue;
	}

	public static String getIDOfChess() {
		return IDOfChess;
	}

	public static void setIDOfChess(String iDOfChess) {
		IDOfChess = iDOfChess;
	}

	/************************************
	 * 向服务器发送的指令函数
	 ************************************/

	public static boolean joinRoom() {
		Message message = new Message();
		System.out.println("ChessClient.joinRoom()" + clientDataClass);
		message.clientDataClass = clientDataClass;
		message.order = Order.JOIN;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean reConect() {// 切换服务器的时候使用
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.RECONECT;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static void joinRoom(InetAddress serverIP) {

	}

	public static void joinRoom(String serverIP) {// 可手动输入

	}

	/*********************************
	 * 执行PlayFrame的命令函数： 下棋、发送消息、退出房间/退出游戏、切换到用户列表、私聊 、申请对战、准备 请求悔棋、求和、认输、
	 * 同意/不同意悔棋、同意/不同意求和、同意/不同意开始、 赢棋、和棋 房主：开始游戏 选择一个用户申请对战 踢人 选择两个用户开始游戏
	 * 把用户设为房主
	 *******************************/
	public static boolean upData() {
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.UPDATA;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean SendServerChess(ChessPoint chessPoint, int count) {
		Message message = new Message();
		message.chessNum = count;
		message.chesspoint = chessPoint;
		message.order = Order.LAST_CHESS;
		message.msg = MessageMSG.CHESS_NUM + MessageMSG.CHESS_POINT + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean exitRoom() {// 退出重新搜索房间
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.EXIT;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			clientDataClass = null;
			isWork = false;
			clientdataVec.clear();
			clientReceive.close();
			if (MainWindowUI.getNetmode() == Netmode.WAN) {
				((SearchJFrameOfWAN) MainWindowUI.getSearchframe()).setVisible(true);
			} else {
				((SearchJFrameOfLAN) MainWindowUI.getSearchframe()).setVisible(true);
			}

			return true;
		} else {
			clientDataClass = null;
			isWork = false;
			clientdataVec.clear();
			clientReceive.close();
			if (MainWindowUI.getNetmode() == Netmode.WAN) {
				((SearchJFrameOfWAN) MainWindowUI.getSearchframe()).setVisible(true);
			} else {
				((SearchJFrameOfLAN) MainWindowUI.getSearchframe()).setVisible(true);
			}
			return false;
		}
	}

	public static boolean goBackMainFrame() {// 回到主界面
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.EXIT;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			clientDataClass = null;
			isWork = false;
			clientdataVec.clear();
			clientReceive.close();
			MainWindowUI.getMainFrame().setVisible(true);
			return true;
		} else {
			clientDataClass = null;
			isWork = false;
			clientdataVec.clear();
			clientReceive.close();
			MainWindowUI.getMainFrame().setVisible(true);
			return false;
		}
	}

	public static boolean kicked() {// 被房主踢出房间
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.KICKED;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			clientDataClass = null;
			isWork = false;
			clientdataVec.clear();
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		clientDataClass = null;
		isWork = false;
		clientdataVec.clear();
		return false;
	}

	public static boolean exitGame() {// 退出整个游戏
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.EXIT;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		sendAndReceive.sendMessage(message);
		Timer timer = new Timer();
		ExitLater exitlater = new ExitLater();
		timer.schedule(exitlater, 3000);
		clientReceive.close();
		return true;
	}

	public static boolean setUpClient() {// 刷新客户列表,只包含Order
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.ASK_ALL_CLIENTS;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean applyFight() {// 进入准备状态或取消准备状态
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.APPLY_FIGHT;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			if (clientDataClass.getAttribute() != 3) {// 只更改本地的客户属性
				clientDataClass.setAttribute(3);
			} else {
				clientDataClass.setAttribute(4);
			}
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean applyFight(InetAddress ip) {// 申请与某人对战,如果不是房主，可能要向房主发送消息
		return true;
	}

	public static boolean askForBack() {
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.BACK;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean askForPeace() {
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.ASK_PEACE;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean askForBegin() {// 房主发送
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.BEGIN;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean askForBegin(ClientDataClass clientDataOpponent) {// 房主发送
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.oppClientDataClass = clientDataOpponent;
		message.order = Order.BEGIN;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.OPP_CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean giveUp() {// 认输要反馈信息给PlayFrame吗,点击按钮的时候应该自己处理了
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.GIVEUP;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean sendBack(boolean b) {
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		if (b) {
			message.order = Order.AGREE_BACK;
			message.chessall = PlayFrame.getChessStack();
			message.chessNum = PlayFrame.getCount();
			message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER + MessageMSG.CHESS_ALL + MessageMSG.CHESS_NUM;
		} else {
			message.order = Order.DISAGREE_BACK;
			message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		}
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean sendPeace(boolean b) {
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		if (b) {
			message.order = Order.AGREE_ASKPEACE;
		} else {
			message.order = Order.DISAGREE_ASKPEACE;
		}
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean sendBegin(boolean b) {
		Message message = new Message();
		if (b) {
			isBegin = true;
			IDOfChess = "" + System.currentTimeMillis();
			clientDataClass.setAttribute(2);
			ClientReceiveThread.getPlayFrame().updateButton();
			message.clientDataClass = clientDataClass;
			message.order = Order.AGREE_BEGIN;
			message.IDOfChess = IDOfChess;
			message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER + MessageMSG.ID_OF_CHESS;
			// 只更改本地的客户属性,服务器自动更新本地所有用户列表
		} else {
			message.clientDataClass = clientDataClass;
			message.order = Order.DISAGREE_BEGIN;
			message.IDOfChess = IDOfChess;
			message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER + MessageMSG.ID_OF_CHESS;
		}
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean rePlay(boolean b) {
		Message message = new Message();
		if (b) {
			message.order = Order.AGREE_REPLAY;
		} else {
			message.order = Order.DISAGREE_REPLAY;
		}
		message.clientDataClass = clientDataClass;
		message.IDOfChess = IDOfChess;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ID_OF_CHESS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean kickClient(ClientDataClass clientDataclass) {// 房主把某人踢出，客户信息要自己向服务器同步
		Message message = new Message();
		message.oppClientDataClass = clientDataclass;
		message.order = Order.KICK;
		message.msg = MessageMSG.OPP_CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			clientdataVec.remove(clientDataclass);
			ClientReceiveThread.getPlayFrame().updateUserList();// 伪操作
			setUpClient();
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean askForAllChess() {
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.ASK_ALL_CHESS;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean win() {
		isBegin = false;
		ClientReceiveThread.getPlayFrame().updateButton();// 释放开始游戏按钮
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.order = Order.WIN;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static void peace() {// 棋盘被下满了棋子和棋

	}
	/*
	 * 新添功能
	 */
	// eg: C:/1.txt 1.txt

	public static boolean sendImageToTemp(String fileAbsolutePath) {
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		if (!message.setFile(fileAbsolutePath)) {
			return false;
		}
		message.order = Order.FILE;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.FILE + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean SendServerChat(StyledDocument sendDoc) {
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.setChatmsg(sendDoc);
		message.order = Order.CHAT;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.CHAT_MSG + MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;
	}

	public static boolean secretChat(ClientDataClass oppClientDataclass, StyledDocument sendDoc) {// 私聊
		Message message = new Message();
		message.clientDataClass = clientDataClass;
		message.oppClientDataClass = oppClientDataclass;
		message.setChatmsg(sendDoc);
		message.order = Order.SECRET_CHAT;
		message.msg = MessageMSG.CLIENT_DATA_CLASS + MessageMSG.OPP_CLIENT_DATA_CLASS + MessageMSG.CHAT_MSG
				+ MessageMSG.ORDER;
		if (sendAndReceive.sendMessage(message)) {
			return true;
		}
		try {
			failMessageQue.offer(message);
		} catch (Exception e) {
			e.printStackTrace();
		}
		return false;

	}
}

class ExitLater extends TimerTask {
	@Override
	public void run() {
		// TODO Auto-generated method stub
		System.exit(0);
	}
}
